package com.lizonghui.googleplay.base;

import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ListView;

import com.lizonghui.googleplay.control.LoadingMoreHolder;
import com.lizonghui.googleplay.factory.ThreadPoolProxyFactory;
import com.lizonghui.googleplay.utils.UIUtils;

import java.util.List;

/**
 * Created by Administrator on 2016/6/19.
 * 对MyBaseAdapter的抽取
 */
public abstract class SuperBaseAdapter<ITEMBEANTYPE> extends MyBaseAdapter implements AdapterView.OnItemClickListener {
    public static final int VIEWTYPE_LOADINGMORE = 0;//加载更多视图
    public static final int VIEWTYPE_NORMAL = 1;//正常视图
    private static final int PAGERSIZE = 20;
    private LoadingMoreHolder mLoadingMoreHolder;
    private LoadMoreTask mLoadMoreTask;
    private AbsListView mMAbsLisView;
    private int mMLoadMoreState;

    public SuperBaseAdapter(AbsListView absListView, List datas) {//传入AbsListView是因为可能子类是listView或者是GirdView
        super(datas);
        this.mMAbsLisView = absListView;//要设置点击监听，所以要拿到ListView,我们让子类去提供
        mMAbsLisView.setOnItemClickListener(this);//拿到absListView后就设置监听
    }

    /**
     * 得到ViewType类型的数目
     * get（得到）ViewType（viewType类型）Count（数目）
     *
     * @return
     */
    @Override
    public int getViewTypeCount() {
        return super.getViewTypeCount() + 1;//(normal条目))+(加载更多条目) = 2个条目
    }


    /**
     * 根据position返回viewType类型
     * 得到具体条目viewType类型。条目的int值必须在0-（count-1）之间
     * get（得到）Item（具体条目）ViewType（类型）
     *
     * @param position
     * @return
     */
    @Override
    public int getItemViewType(int position) {
        //当滑到底时候才是加载更多视图
        if (position == getCount() - 1) {
            return VIEWTYPE_LOADINGMORE;
        } else {
            return getNormalItemViewType(position);//1 或者 2
        }
    }

    /**
     * 得到普通条目的ViewType类型
     *
     * @param position
     * @return
     * @des 子类可以复写该方法，返回更多条目的ViewType类型
     */
    public int getNormalItemViewType(int position) {
        return VIEWTYPE_NORMAL;//默认返回1
    }


    /**
     * ListView中显示几种viewType类型
     * 1.复写2个方法getViewTypeCount，getItemViewType
     * 2.在getView分vie处理
     *
     * @param position
     * @param convertView
     * @param parent
     * @return
     */

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        /**
         * 系统返回convertView之前会判断即将展示的rootView和已经缓存好的convertView的viewType类型是否一致
         */
        /*=================== 决定根布局==================*/
        BaseHolder baseHolder = null;
        if (convertView == null) {
            if (getItemViewType(position) == VIEWTYPE_LOADINGMORE) {//加载更多视图
                baseHolder = getLoadingMoreHolder();
            } else {
                //根据具体类型选择视图
                baseHolder = getSpecialHolder(position);//正常视图

            }

        } else {
//          baseHolder = (ItemHolder) convertView.getTag();//当多加了一个viewType时候，返回的就不一定是HomeHolder
            baseHolder = (BaseHolder) convertView.getTag();//这里返回值用BaseHolder相当于多态
        }
            /*=================== 接收数据，绑定数据==================*/
        if (getItemViewType(position) == VIEWTYPE_LOADINGMORE) {
            //这里不一定要触发，因为可能没有更多数据了
            if (hasLoadMore()) {
                triggerLoadMore();//如果有更多加载，才加载.异步处理
            } else {
                baseHolder.setDataAndRefreshHolderView(LoadingMoreHolder.LOADMORE_NONE);//参数要加类名
            }

        } else {
            //根据具体类型，选择数据绑定方式
            baseHolder.setDataAndRefreshHolderView(mDataSet.get(position));
        }
        return baseHolder.mHolderView;
    }


    private void triggerLoadMore() {
        //处理loadMorHolder的UI
        mMLoadMoreState = LoadingMoreHolder.LOADMORE_LOADING;
        mLoadingMoreHolder.setDataAndRefreshHolderView(mMLoadMoreState);

        if (mLoadMoreTask == null) {
            mLoadMoreTask = new LoadMoreTask();
            ThreadPoolProxyFactory.createNormalThreadPoolProxy().execute(mLoadMoreTask);
        }

    }

    private class LoadMoreTask implements Runnable {
        @Override
        public void run() {

            List<ITEMBEANTYPE> loadMoreList = null;
            int state = LoadingMoreHolder.LOADMORE_LOADING;

             /*---------------加载数据，得到数据，处理数据-------------------*/
            try {
                loadMoreList = initLoadMoreData();
                /*---------------根据数据，得到状态-------------------*/
                if (loadMoreList.size() == 0) {
                    state = LoadingMoreHolder.LOADMORE_NONE;//没有更多了
                } else if (loadMoreList.size() == PAGERSIZE) { //根据分页协议，每页20条数据
                    state = LoadingMoreHolder.LOADMORE_LOADING;//还有可能加载更多-->给用户看就是loading状态
                } else {//只能是size<20
                    state = LoadingMoreHolder.LOADMORE_NONE;
                }
            } catch (Exception e) {
                e.printStackTrace();
                state = LoadingMoreHolder.LOADMORE_ERROR;
            }
            //UI刷新要通过消息机制
            //这里自动复制两个变量，是因为它子线程要final，但外部的状态需要变动
            final List<ITEMBEANTYPE> finalLoadMoreList = loadMoreList;
            final int finalState = state;
            UIUtils.postTaskSafely(new Runnable() {
                @Override
                public void run() {
                    /*---------------根据数据，刷新UI-------------------*/
                /*--------------刷新UI，得到一个list集合，刷新ListView-------------------*/
                    if (finalLoadMoreList != null) {
                        mDataSet.addAll(finalLoadMoreList);//把更多的数据全部加载到数据集合中
                        notifyDataSetChanged();//更新数据
                    }
                /*--------------刷新UI，得到一个最新date刷新LoadMoreHolder状态------------------*/
                    mLoadingMoreHolder.setDataAndRefreshHolderView(finalState);


                }
            });
            //置空加载更多任务,任务执行完毕
            mLoadMoreTask = null;
        }
    }

    /**
     * @return
     * @des 真正开始在子线程加载更多数据
     * @call listView滑到底时候调用，当没有加载更多时候就用不到这个方法
     */
    public List<ITEMBEANTYPE> initLoadMoreData() throws Exception {
        /**
         * 1方法提上掏出的异常，抛到哪里去了？
         *      抛到调用处
         * 2什么时候需要定义方法时候抛出异常？
         *      方法调用处，会根据抛出异常，处理不同的逻辑的时候
         */
        return null;
    }


    /**
     * @return 是否还有更多数据要加载
     * @des 子类决定是否加载更多数据
     */
    protected boolean hasLoadMore() {
        return false;
    }


    /**
     * 返回BaseHolder的子类
     */
    private BaseHolder getLoadingMoreHolder() {
//        return new LoadingMoreHolder();//这里不用每次都new一个应用里面只new一次就可以了
        mLoadingMoreHolder = new LoadingMoreHolder();
        return mLoadingMoreHolder;
    }

    /**
     * @param position
     * @return
     * @des 返回一个BaseHolder的子类对象
     * @call 走到getView方法时候，且（convertView == null）时候调用
     */
    public abstract BaseHolder getSpecialHolder(int position);

    /*-------------处理点击重试操作，这里是给mMabsListView设置的点击事件-------------*/
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        //这里position由于加入了headView会导致错乱，我们加以修正
        if(mMAbsLisView instanceof ListView){
            position = position - ((ListView) mMAbsLisView).getHeaderViewsCount();
        }

        if (getItemViewType(position) == VIEWTYPE_LOADINGMORE) {
            if (mMLoadMoreState == LoadingMoreHolder.LOADMORE_ERROR) {
                triggerLoadMore();
            }
        } else {
            //在这里不知道点击普通条目应该做什么？不知道，交给子类去做
            onNormalItemClick(parent, view, position, id);
        }
    }






    /**
     * 点击了普通条目
     *
     * @param parent
     * @param view
     * @param position
     * @param id
     */
    public void onNormalItemClick(AdapterView<?> parent, View view, int position, long id) {

    }
}
